
const {ccclass, property} = cc._decorator;

cc.log = console.log;

@ccclass
export default class NewClass extends cc.Component {

    @property(cc.Label)
    progressLbl : cc.Label = null;

    //必须用这种方式定义
    @property({
        type : cc.Asset
    })
    manifestUrl : cc.Asset = null;
    

    _updating : boolean = false;
    _canRetry : boolean = false;
    _storagePath : string = "";
    _failCount : number = 0;

    _am : any = null;

    versionCompareHandle (versionA, versionB) {
        cc.log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);
        var vA = versionA.split('.');
        var vB = versionB.split('.');
        for (var i = 0; i < vA.length; ++i) {
            var a = parseInt(vA[i]);
            var b = parseInt(vB[i] || 0);
            if (a === b) {
                continue;
            }
            else {
                return a - b;
            }
        }
        if (vB.length > vA.length) {
            return -1;
        }
        else {
            return 0;
        }
    };


    onClickBtn(){
        cc.log('----测试用的点击函数的log----');
    };


    /**
     * 热更新回调函数
     * @param event 
     */
    updateCb(event) {
        var needRestart = false;
        var failed = false;
        switch (event.getEventCode())
        {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                cc.log('本地manifest文件未配置，热更新失败');
                failed = true;
                break;
            case jsb.EventAssetsManager.UPDATE_PROGRESSION:
                cc.log('正在进行热更新操作');
                // this.panel.byteProgress.progress = event.getPercent();
                // this.panel.fileProgress.progress = event.getPercentByFile();

                // this.panel.fileLabel.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
                // this.panel.byteLabel.string = event.getDownloadedBytes() + ' / ' + event.getTotalBytes();

                this.progressLbl.string = event.getPercent() + '%';

                if(event.getPercent() >= 100){
                    cc.log('---5s钟后进入GameScene---');
                    this.scheduleOnce(function(){
                        
                    },5.0);
                }

                var msg = event.getMessage();
                if (msg) {
                    cc.log('Updated file: ' + msg);
                    // cc.log(event.getPercent()/100 + '% : ' + msg);
                }
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                cc.log('下载manifest文件失败，热更失败');
                failed = true;
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                cc.log('本地已是最新版本，无需热更，热更失败');
                failed = true;
                break;
            case jsb.EventAssetsManager.UPDATE_FINISHED:
                // cc.log('Update finished. ' + event.getMessage());
                cc.log('热更结束：'+ event.getMessage());
                needRestart = true;
                break;
            case jsb.EventAssetsManager.UPDATE_FAILED:
                // cc.log('Update failed. ' + event.getMessage());
                cc.log('热更失败：' + event.getMessage())
                // this.panel.retryBtn.active = true;
                this._updating = false;
                this._canRetry = true;
                break;
            case jsb.EventAssetsManager.ERROR_UPDATING:
                // cc.log('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
                cc.log('Asset 更新失败 ， error : ' + event.getAssetId() + ' , ' + event.getMessage());
                break;
            case jsb.EventAssetsManager.ERROR_DECOMPRESS:
                // cc.log("event.getMessage() = " , event.getMessage());
                cc.log('解压失败：' +  event.getMessage());
                break;
            default:
                break;
        }

        if (failed) {
            this._am.setEventCallback(null);
            this._updating = false;
        }

        if (needRestart) {
            this._am.setEventCallback(null);
            // this._updateListener = null;
            // Prepend the manifest's search path
            var searchPaths = jsb.fileUtils.getSearchPaths();
            var newPaths = this._am.getLocalManifest().getSearchPaths();
            console.log(JSON.stringify(newPaths));
            Array.prototype.unshift.apply(searchPaths, newPaths);
            // This value will be retrieved and appended to the default search path during game startup,
            // please refer to samples/js-tests/main.js for detailed usage.
            // !!! Re-add the search paths in main.js is very important, otherwise, new scripts won't take effect.
            cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
            jsb.fileUtils.setSearchPaths(searchPaths);

            cc.audioEngine.stopAll();
            cc.game.restart();
        }
    };

    /**
     * 进行热更新
     */
    hotUpdate(){
        // if (this._am && !this._updating) {
        //     this._am.setEventCallback(this.updateCb.bind(this));

        //     if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
        //         // Resolve md5 url
        //         var url = this.manifestUrl.nativeUrl;
        //         if (cc.loader.md5Pipe) {
        //             url = cc.loader.md5Pipe.transformURL(url);
        //         }
        //         this._am.loadLocalManifest(url);
        //     }

        //     this._failCount = 0;
        //     this._am.update();
        //     this._updating = true;
        // }

        if (this._am ) {
            this._am.setEventCallback(this.updateCb.bind(this));

            if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
                // Resolve md5 url
                var url = this.manifestUrl.nativeUrl;
                if (cc.loader.md5Pipe) {
                    url = cc.loader.md5Pipe.transformURL(url);
                }
                this._am.loadLocalManifest(url);
            }

            this._failCount = 0;
            this._am.update();
        }

    };

    /**
     * 检查是否有更新的回调
     * @param event 
     */
    checkCb (event) {
        cc.log('Code: ' + event.getEventCode());
        switch (event.getEventCode())
        {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                cc.log("No local manifest file found, hot update skipped.");
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                cc.log("Fail to download manifest file, hot update skipped.");
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                cc.log("Already up to date with the latest remote version.");
                break;
            case jsb.EventAssetsManager.NEW_VERSION_FOUND:
                cc.log('New version found, please try to update.');
                this.hotUpdate();//进行热更新
                break;
            default:
                return;
        }
        
        this._am.setEventCallback(null);
        // this._checkListener = null;
        this._updating = false;
    };

    /**
     * 检查是否有热更新
     */
    checkUpdate(){
        // if(this._updating){
        //     cc.log('Checking or updating ...');
        //     return;
        // }
        if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
            // Resolve md5 url
            var url = this.manifestUrl.nativeUrl;
            if (cc.loader.md5Pipe) {
                url = cc.loader.md5Pipe.transformURL(url);
            }
            this._am.loadLocalManifest(url);
        }
        if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
            cc.log('Failed to load local manifest ...');
            return;
        }
        this._am.setEventCallback(this.checkCb.bind(this));

        this._am.checkUpdate();
        // this._updating = true;
    };



    // loadCustomManifest() {
    //     // if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
    //     //     var manifest = new jsb.Manifest(customManifestStr, this._storagePath);
    //     //     this._am.loadLocalManifest(manifest, this._storagePath);
    //     //     cc.log('Using custom manifest');
    //     // }
    // };
    
    retry() {
        if (!this._updating && this._canRetry) {
            this._canRetry = false;
            cc.log('Retry failed Assets...');
            this._am.downloadFailedAssets();
        }
    };

    /**
     * 初始化热更新模块
     */
    initHotUpdate(){

        if(!cc.sys.isNative){
            cc.log('非原生平台！！！');
            cc.log('直接进入登录界面');
            return;
        }
        this._storagePath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'hotupdate-remote-asset';
        cc.log('Storage path for remote asset :' + this._storagePath);
        // Init with empty manifest url for testing custom manifest
        this._am = new jsb.AssetsManager('',this._storagePath,this.versionCompareHandle);

        this._am.setVerifyCallback(function (path, asset) {
            // When asset is compressed, we don't need to check its md5, because zip file have been deleted.
            var compressed = asset.compressed;
            // Retrieve the correct md5 value.
            var expectedMD5 = asset.md5;
            // asset.path is relative path and path is absolute.
            var relativePath = asset.path;
            // The size of asset file, but this value could be absent.
            var size = asset.size;
            if (compressed) {
                cc.log("Verification passed : " + relativePath);
                return true;
            }
            else {
                cc.log("Verification passed : " + relativePath + ' (' + expectedMD5 + ')');
                return true;
            }
        });

        cc.log('Hot update is ready , please check or directly update');

        if(cc.sys.os === cc.sys.OS_ANDROID){
            // Some Android device may slow down the download process when concurrent tasks is too much.
            // The value may not be accurate, please do more test and find what's most suitable for your game.
            this._am.setMaxConcurrentTask(2);
            cc.log('android 设备 Max concurrent tasks count have been limited to 2');
        }

        this.checkUpdate();

    };

    onLoad(){

        this.initHotUpdate();

    };

    onDestroy(){
        this._am && (this._am.setEventCallback(null));
    };

}
